/**
 * 
 */
package Project2.cs342.project1.mathNotebook.gui;

import java.awt.*;

import Project2.cs342.project1.mathNotebook.expressions.*;
import Project2.cs342.project1.mathNotebook.expressions.exceptions.UncapturedVariableException;
import Project2.cs342.project1.mathNotebook.notebook.*;
import javax.swing.*;

/**
 * Shows a graph
 * 
 * @author Jared Schlicht
 */
public class Graph extends JPanel {
    private NotebookEntry entry;
    private final double delta = 0.001;

    public Graph() {
	this.setBackground(Color.white);
    }

    public void drawGraph(NotebookEntry entry) {
	this.entry = entry;
	this.repaint();
    }

    private void drawOrigin(Graphics graphics) {
	int minScreenY = screenYCoord(this.entry.minYCoordinate);
	int maxScreenY = screenYCoord(this.entry.maxYCoordinate);
	int minScreenX = screenXCoord(this.entry.minXCoordinate);
	int maxScreenX = screenXCoord(this.entry.maxXCoordinate);
	int yZero = screenYCoord(0);
	int xZero = screenXCoord(0);

	graphics.setColor(Color.black);

	// x=0
	graphics.drawLine(xZero, minScreenY, xZero, maxScreenY);
	// y=0
	graphics.drawLine(minScreenX, yZero, maxScreenX, yZero);
    }

    @Override
    protected void paintComponent(Graphics graphics) {
	// Clears any previously drawn lines
	super.paintComponent(graphics);

	if (this.entry != null) {	   
		//System.out.println("Is drawing");
	    this.drawOrigin(graphics);

	    // Draws the equation
	    graphics.setColor(Color.red);
	    double currentX = this.entry.minXCoordinate;
	    while (currentX < this.entry.maxXCoordinate) {
		EvaluationVisitor visitor = new EvaluationVisitor("x", currentX);
		try {
		    double yCoordinate = (Double) this.entry.function
			    .accept(visitor);
		    int screenX = screenXCoord(currentX);
		    int screenY = screenYCoord(yCoordinate);
		    graphics.drawLine(screenX, screenY, screenX, screenY);
		} catch (UncapturedVariableException e) {
		}

		currentX += delta;
	    }

	    // Draws the tangent lines
	    graphics.setColor(Color.cyan);
	    for (Double tangentPoint : this.entry.tangentPoints) {
		Expr tanLine = this.entry.getTangentLineAt(tangentPoint);
		currentX = this.entry.minXCoordinate;
		while (currentX < this.entry.maxXCoordinate) {
		    EvaluationVisitor visitor = new EvaluationVisitor("x",
			    currentX);
		    try {
			double yCoordinate = (Double) tanLine.accept(visitor);
			int screenX = screenXCoord(currentX);
			int screenY = screenYCoord(yCoordinate);
			graphics.drawLine(screenX, screenY, screenX, screenY);
		    } catch (UncapturedVariableException e) {
		    }
		    currentX += delta;
		}
	    }
	}
    }

    /**
     * Converts a cartesian x coordinate to a screen x coordinate. Adapted from
     * http://buildingblocksjava.com/drawing-lines/
     * 
     * @author Jared Schlicht
     * @param x
     *            cartesian x coordinate
     * @return screen x coordinate
     */
    private int screenXCoord(double x) {
	double minX = entry.minXCoordinate;
	double maxX = entry.maxXCoordinate;
	// return (int)((x * (maxX-minX)/(this.getWidth()-1)));
	return (int) ((x - minX) * (this.getWidth() - 1) / (maxX - minX));
    }

    /**
     * Converts a cartesian y coordinate to a screen y coordinate. Adapted from
     * http://buildingblocksjava.com/drawing-lines/
     * 
     * @author Jared Schlicht
     * @param y
     *            cartesian y coordinate
     * @return screen y coordinate
     */
    private int screenYCoord(double y) {
	double minY = entry.minYCoordinate;
	double maxY = entry.maxYCoordinate;
	int height = this.getHeight();
	return height - (int) ((y - minY) * (height - 1) / (maxY - minY));
    }

    /*
     * @Override public void paint(Graphics graphics) { if (this.entry != null)
     * { double currentX = this.entry.minXCoordinate; while (currentX <
     * this.entry.maxXCoordinate) { EvaluationVisitor visitor = new
     * EvaluationVisitor("x", currentX); try { double yCoordinate =
     * (Double)this.entry.function.accept(visitor); this.drawPoint(graphics,
     * currentX, yCoordinate); } catch (UncapturedVariableException e) { }
     * 
     * currentX += delta; } } }
     */
}
